package com.mmx.baseservice.common.wechat.pay.controller;

import com.alibaba.fastjson.JSONObject;
import com.mmx.baseservice.admin.pojo.AdInfo;
import com.mmx.baseservice.common.utils.CommUtil;
import com.mmx.baseservice.common.utils.UUIDUtil;
import com.mmx.baseservice.common.utils.returnbody.ReturnBody;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxScanPayNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.UnknownHostException;


/**
 * 微信支付示例代码
 * @author Binary Wang
 */
@Api(tags = "微信支付")
@RestController
@RequestMapping(value = "wx/pay", produces = "text/plain;charset=utf-8")
public class WxPayController {

    @Resource
    private WxPayService wxPayService;
    @Resource
    private HttpServletRequest request;

    @ApiOperation(value = "查询订单")
    @ApiImplicitParams({
        @ApiImplicitParam(paramType = "query", dataTypeClass = String.class, name = "transactionId", value = "微信订单号"),
        @ApiImplicitParam(paramType = "query", dataTypeClass = String.class, name = "outTradeNo", value = "商户系统内部的订单号，当没提供transactionId时需要传这个"),
    })
    @PostMapping("/queryOrder")
    public WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxPayException {
        return this.wxPayService.queryOrder(transactionId, outTradeNo);
    }

    @ApiOperation(value = "统一下单（JSAPI支付）")
    @ApiImplicitParam(paramType = "query", dataTypeClass = String.class, name = "money", value = "支付金额")
    @PostMapping("/createJsApiOrder")
    public String createJsApiOrder(Double money) {
        // TODO 获取OPENID
        String openId = "";
        // 订单号
        String outTradeNo = UUIDUtil.getTimeId().toString();
        // 自定义参数，回调时原样返回
        String attach = "自定义参数，回调时原样返回";
        // 支付金额，单位：分
        BigDecimal totalAmount = BigDecimal.valueOf(money).multiply(BigDecimal.valueOf(100));
        // 回调路径
        String url = request.getRequestURL().toString();
        url = url.substring(0, url.lastIndexOf("/"));
        WxPayUnifiedOrderRequest payRequest;
        try {
            payRequest = WxPayUnifiedOrderRequest.newBuilder().outTradeNo(outTradeNo)
                    .openid(openId).body("在线支付").totalFee(totalAmount.intValue())
                    .spbillCreateIp(InetAddress.getLocalHost().getHostAddress()).tradeType("JSAPI")
                    .productId("10000").notifyUrl(url + "/public/notifyPay")
                    .attach(attach).build();
            WxPayMpOrderResult order = this.wxPayService.createOrder(payRequest);
            order.setAppId(null);
            return ReturnBody.success(order);
        } catch (UnknownHostException | WxPayException e) {
            e.printStackTrace();
            return ReturnBody.error("统一下单失败");
        }
    }

    @ApiIgnore
    @ApiOperation(value = "支付回调通知处理")
    @PostMapping("/public/notifyPay")
    public String parseOrderNotifyResult(@RequestBody String xmlData) throws WxPayException {
        final WxPayOrderNotifyResult notifyResult = this.wxPayService.parseOrderNotifyResult(xmlData);
        // TODO 业务逻辑处理，注意幂等性验证

        return WxPayNotifyResponse.success("成功");
    }

    @ApiOperation(value = "会员充值")
    @PostMapping("us/memberRecharge/qrCode")
    public String memberRecharge(Double money){
        Long usId = (Long)request.getAttribute(AdInfo.ID);
        JSONObject attach = new JSONObject();
        attach.put("usId", usId);
        attach.put("type", 1);
        String body = "会员充值";
        return createQrCodeOrder(money, attach.toJSONString(), body);
    }

    /**
     * 扫码支付
     * @param money 金额
     * @param attach 自定义参数
     * @param body
     * @return
     */
    public String createQrCodeOrder(Double money, String attach, String body) {
        if (money < 0.01) {
            return ReturnBody.error("输入的金额不正确");
        }
        // 订单号
        String outTradeNo = UUIDUtil.getCode().toString();
        // 支付金额，单位：分
        BigDecimal totalAmount = BigDecimal.valueOf(money).multiply(BigDecimal.valueOf(100));
        // 回调路径
        String url = request.getRequestURL().toString();
        url = url.substring(0, url.lastIndexOf("/"));
        WxPayUnifiedOrderRequest payRequest;
        try {
            payRequest = WxPayUnifiedOrderRequest.newBuilder()
                    .outTradeNo(outTradeNo)
                    .body(body)
                    .totalFee(totalAmount.intValue())
                    .spbillCreateIp(InetAddress.getLocalHost().getHostAddress())
                    .tradeType("NATIVE")
                    .productId("10000")
                    .notifyUrl(url + "/public/notifyQrPay")
                    .attach(attach)
                    .build();
            WxPayNativeOrderResult order = this.wxPayService.createOrder(payRequest);
            return ReturnBody.success(order.getCodeUrl());
        } catch (UnknownHostException | WxPayException e) {
            e.printStackTrace();
            return ReturnBody.error("统一下单失败");
        }
    }


    @ApiIgnore
    @ApiOperation(value = "扫码支付回调通知处理")
    @PostMapping("/public/notifyQrPay")
    public String parseScanPayNotifyResult(String xmlData) throws WxPayException {
        final WxScanPayNotifyResult result = this.wxPayService.parseScanPayNotifyResult(xmlData);
        // TODO 业务逻辑处理，注意幂等性验证

        return WxPayNotifyResponse.success("成功");
    }

}

